<template>
  <!-- 使用Vant组件库的导航栏组件，设置标题、左边文本、显示返回箭头，并绑定点击左边返回按钮的事件 -->
  <van-nav-bar title="聊天室" left-text="返回" left-arrow @click-left="onClickLeft" />

  <!-- 聊天房间的根组件 -->
  <div class="chat-room">
    <!-- 用于展示聊天消息的容器 -->
    <div class="chat-messages" ref="messageContainer">
      <!-- 循环遍历聊天消息列表，根据消息发送者及消息类型进行不同展示 -->
      <div v-for="(msg, index) in messages" :key="index" :class="msg.isMe ? 'my-message' : 'other-message'">
        <!-- 如果消息类型为图片，展示图片 -->
        <img v-if="msg.isImage" class="end-img" :src="msg.content" alt="图片消息" />
        <!-- 如果不是图片消息，展示文本内容 -->
        <div v-else class="message-content">
          {{ msg.content }}
        </div>
        <!-- 根据消息是否是自己发送的，动态绑定头像图片的类名和src属性，以显示不同的头像 -->
        <img :class="msg.isMe ? 'left-img' : 'right-img'" :src="msg.isMe ? rightImg : leftImg" alt="" />
      </div>
    </div>
    <!-- 聊天输入区域的容器 -->
    <div class="chat-input">
      <!-- 输入框，双向数据绑定，监听回车键按下事件来发送消息 -->
      <input v-model="inputMessage" placeholder="请输入消息" @keyup.enter="sendMessage" />
      <!-- 表情选择按钮，点击切换表情选择器显示隐藏 -->
      <button @click="toggleEmojiPicker">😄</button>

      <!-- 图片上传按钮，点击调用发送图片函数 -->
      <button @click="sendImage">图片</button>
      <!-- 表情选择器组件，绑定相关属性和事件 -->
      <!-- 发送按钮，点击触发发送消息函数 -->
      <button @click="sendMessage">发送</button>
      <!-- 自定义组件表情  emojiHandle传递点击事件  all的值决定展示所有表情还是默认表情 v-if控制显示还是隐藏-->
      <Emoji @emojiHandle="emojiHandle" :all="true" v-if="emojiPickerVisible" />

    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick } from "vue";
import Emoji from '../components/chatroom/index.vue';

// 定义点击导航栏左边返回按钮的函数，调用浏览器历史记录的回退功能
const onClickLeft = () => history.back();

// 定义自己的头像图片路径，从本地存储获取（需确保存储中有对应的值且路径正确）
const rightImg = ref<string | null>(localStorage.getItem('img'));
// 定义对方的头像图片路径
const leftImg = ref<string>('https://kano.guahao.cn/83V63540551?webp=80');

// 定义用于存储聊天消息的响应式数组，用来存放聊天过程中的所有消息记录
const messages = ref<any[]>([]);
// 定义用于绑定输入框消息内容的响应式变量，双向绑定输入框中的文本内容
const inputMessage = ref("");
// 定义用于获取聊天消息容器DOM元素的响应式变量，后续用于操作消息容器的滚动等功能
const messageContainer = ref<HTMLElement | null>(null);
// 定义用于控制表情选择器显示隐藏状态的响应式变量，初始值为隐藏
const emojiPickerVisible = ref(false);
// 定义用于存储WebSocket实例的响应式变量，初始为null，用于和WebSocket服务器进行通信
const socket = ref<WebSocket | null>(null);

// 组件挂载完成后的生命周期钩子，进行WebSocket连接相关操作
onMounted(() => {
  // 创建WebSocket连接，连接到本地的8080端口（假设此处有对应的WebSocket服务器在运行）
  socket.value = new WebSocket("ws://localhost:8080");
  socket.value.onopen = () => {
    console.log("已连接到WebSocket服务器");
  };
  socket.value.onmessage = (event: { data: string }) => {
    const data = JSON.parse(event.data);
    // 将接收到的消息添加到消息列表，处理消息类型标识，比如是否为图片消息等
    messages.value.push({
      isMe: false,// 标记接收到的消息为对方发送的
      content: data.content,
      isImage: data.isImage || false,
    });
    // 确保DOM更新后滚动消息容器到底部，展示最新消息，保证用户能及时看到新消息
    nextTick(scrollToBottom);
  };
  socket.value.onclose = () => {
    console.log("与WebSocket服务器的连接已关闭");
  };
});

// 点击发送消息
const sendMessage = () => {
  if (inputMessage.value) {
    const messageObj = {
      content: inputMessage.value,
    };
    if (socket.value) {
      try {
        socket.value.send(JSON.stringify(messageObj));
        // 将自己发送的消息添加到消息列表，记录自己发送的文本消息内容
        messages.value.push({
          isMe: true,// 标记自己发送的消息
          content: inputMessage.value,
        });
        inputMessage.value = "";
        nextTick(scrollToBottom);
      } catch (error) {
        console.error("发送消息到服务器出错:", error);
        alert("消息发送失败，请稍后重试");
      }
    } else {
      alert("尚未连接到服务器，请稍后再试");
    }
  }
};

// 点击表情，将表情添加到输入框消息内容中的函数，实现表情插入功能
const emojiHandle = (emoji: string) => {
  inputMessage.value += emoji;
};

// 切换表情选择器显示与隐藏状态的函数，通过取反操作来切换显示隐藏
const toggleEmojiPicker = () => {
  emojiPickerVisible.value = !emojiPickerVisible.value;
};

// 发送图片的函数，模拟点击图片按钮后选择并发送图片的操作流程，基本逻辑不变，此处省略重复代码，可参考之前示例
const sendImage = () => {
  // 创建一个input元素，类型为文件上传类型，用于触发文件选择对话框
  const imageInput = document.createElement('input');
  imageInput.type = 'file';
  // 设置可接受的文件类型为图片类型（所有常见图片格式）
  imageInput.accept = 'image/*';
  // 绑定文件选择后的回调函数，当用户选择完文件后会触发此函数
  imageInput.onchange = async () => {
    // 获取用户选择的文件，这里只取第一个文件（如果用户选择了多个文件，只处理第一个）
    const file = imageInput.files[0];
    if (file) {
      // 创建一个FileReader对象，用于读取文件内容，常用于将文件转换为Base64编码等格式
      const reader = new FileReader();
      reader.onload = (e) => {
        // 获取读取后的文件内容结果，这里的结果是Base64编码后的图片数据字符串（假设读取的是图片文件）
        const imageSrc = e.target.result as string;
        // 将图片消息添加到消息列表，标记此消息为图片消息，并设置图片的Base64编码数据作为消息内容
        messages.value.push({
          isMe: true,
          content: imageSrc,
          isImage: true,
        });
        // 确保DOM更新后滚动消息容器到底部，展示最新的图片消息
        nextTick(scrollToBottom);
        // 构造包含图片信息（Base64编码数据和图片消息标识）的对象，准备发送给服务器
        const messageObj = { message: imageSrc, isImage: true };
        if (socket.value) {
          try {
            socket.value.send(JSON.stringify(messageObj));
          } catch (error) {
            console.error("发送图片消息到服务器出错:", error);
            alert("图片发送失败，请检查网络或服务器配置");
          }
        } else {
          alert("尚未连接到服务器，无法发送图片，请稍后再试");
        }
      };
      reader.readAsDataURL(file);
    }
  };
  // 模拟点击文件选择input元素，触发文件选择对话框弹出，让用户选择图片文件
  imageInput.click();
};

// 将聊天消息容器滚动到最底部的函数，确保最新消息可见，操作消息容器的滚动条位置
const scrollToBottom = () => {
  const container = messageContainer.value;
  if (container) {
    container.scrollTop = container.scrollHeight;
  }
};

</script>

<style scoped>
/* 聊天房间整体样式，设置宽度、居中、边框及溢出隐藏等，使聊天房间在页面中布局合理美观 */
.chat-room {
  width: 100%;
  margin: 0 auto;
  border: 1px solid #ccc;
  border-radius: 0.05rem;
  overflow: hidden;
}

/* 聊天消息容器样式，设置高度、垂直滚动及内边距，方便查看聊天历史消息，并且能滚动显示更多消息 */
.chat-messages {
  height: 3rem;
  overflow-y: auto;
  padding: 0.1rem;
}

/* 自己发送消息 */
.my-message {
  text-align: right;
  display: flex;
  align-content: stretch;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-top: 0.1rem;
}

/* 别人发送消息 */
.other-message {
  margin-top: 0.1rem;
  display: flex;
  text-align: left;
  flex-wrap: nowrap;
  flex-direction: row-reverse;
  justify-content: flex-end;
}

/* 消息内容通用样式，设置为内联块元素，添加内边距、圆角及背景颜色等，使消息文本展示更清晰美观 */
.message-content {
  display: inline-block;
  padding: 0.08rem 0.12rem;
  border-radius: 0.1rem;
  background-color: #e6e6e6;
  max-width: 70%;
  margin-left: 0.1rem;
}

/* 自己发送消息的内容样式，设置不同背景和文字颜色，便于区分自己和对方发送的消息 */
.my-message.message-content {
  background-color: #0084ff;
  color: white;
}

/* 聊天输入区域样式，使用flex布局并添加内边距，方便内部输入框和按钮等元素的排列布局 */
.chat-input {
  display: flex;
  padding: 0.1rem;
  border-top: 1px solid #ccc;
}

/* 聊天输入框样式，设置flex占比、内边距、边框及圆角等，使其在输入区域中占合适比例且样式美观 */
.chat-input input {
  flex: 1;
  padding: 0.05rem;
  border: 1px solid #ccc;
  border-radius: 0.05rem;
}

/* 聊天输入区域按钮样式，设置边距、内边距、无边框、圆角、背景及文字颜色等，统一按钮的外观样式 */
.chat-input button {
  margin-left: 0.1rem;
  padding: 0.05rem 0.05rem;
  border: none;
  border-radius: 0.05rem;
  background-color: #0084ff;
  color: white;
}

/* 自己发送消息的头像样式，设置尺寸、圆角及左边距等属性，使头像展示合适且美观 */
.left-img {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  margin-left: 0.1rem;
}

/* 别人发送消息的头像样式，设置尺寸、圆角等属性，统一头像的展示样式 */
.right-img {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
}

/* 图片消息样式，设置宽度、高度、边距及圆角等，使其展示更美观，在聊天消息中图片能以合适的样式呈现 */
.end-img {
  width: 50%;
  height: 50%;
  margin: 0.1rem;
  border-radius: 0.1rem;
}
</style>